package com.hb.trade.server.project.proj.service.impl;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hb.core.pojo.Attachments;
import com.hb.core.pojo.OrganizeInfo;
import com.hb.core.pojo.project.proj.enums.BidWayEnum;
import com.hb.trade.server.project.proj.manager.AbstractProjectManager;
import com.hb.trade.server.project.proj.service.ProjectService;
import com.hb.trade.server.project.util.DataDockConfig;
import org.fzzn.core.model.enums.AuditStatusEnum;
import com.hb.core.pojo.enums.CommonTypeEnum;
import org.fzzn.core.model.enums.LogicEnum;
import com.hb.core.pojo.enums.ProjectTypeEnum;
import com.hb.core.pojo.project.proj.entity.*;
import com.hb.core.pojo.project.proj.mapper.ProjectMapper;
import com.hb.core.pojo.project.section.dto.BidSectionDTO;
import com.hb.trade.server.project.section.service.raw.BidSectionService;
import lombok.SneakyThrows;
import org.fzzn.core.util.Enums;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 项目信息表 服务实现类
 * </p>
 *
 * @author zhaojk
 * @since 2021-08-30
 */
@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, AbstractProject> implements ProjectService {

    protected final BidSectionService bidSectionService;

    public ProjectServiceImpl(BidSectionService bidSectionService) {
        this.bidSectionService = bidSectionService;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean insertProjectWithoutAudit(JSONObject projectJSON, BidWayEnum bidWay) {
        //TODO 项目现在不需要审核直接设置为 审核通过
        projectJSON.putOpt("auditStatus", AuditStatusEnum.PASSED.getCode());
        // 父类类型指向的是子类的实例
        AbstractProject project = AbstractProjectManager.getInstance(bidWay, projectJSON);
        // 获取实际需要添加的字段
        List<String> selectFields = AbstractProjectManager.getSelectFields(bidWay, true);
        // 保存项目
        boolean projectResult = insertOrUpdateProject(project, selectFields);
        // 保存标段
        JSONArray sectionJSONArray = projectJSON.getJSONArray("sections");
        List<BidSectionDTO> sections = sectionJSONArray.toList(BidSectionDTO.class);
        boolean result = bidSectionService.saveSections(project.getId(), project.getProjectCode(), project.getTenderProjectCode(), project.getSignUpFlag(), sections);
        return projectResult && result;
    }

    @Override
    public IPage<AbstractProject> pageProjects(QueryProject query) {
        return pageProjects(query, null);
    }

    @Override
    public IPage<AbstractProject> pageProjects(QueryProject query, BidWayEnum bidWay) {
        Page<AbstractProject> pages = query.pages();
        // 查询所有项目信息
        baseMapper.projectPages(pages, query);
        // 处理数据
        for (AbstractProject item : pages.getRecords()) {
            item.setBidWayName(Enums.nameOf(BidWayEnum.class, bidWay));
            //项目类型
            item.setProjectTypeName(Enums.nameOf(ProjectTypeEnum.class, item.getProjectType()));

            if (Enums.equals(LogicEnum.YES, query.getWithSections())) {
                // 查询标段
                List<BidSectionDTO> sections = bidSectionService.findByProjectId(item.getId());
                item.setSections(sections);
            }
        }
        return pages;
    }

    @Override
    public AbstractProject getByPrimaryKey(Long projectId, BidWayEnum bidWay) {
        if (projectId == null) {
            return null;
        }
        List<String> selectFields = AbstractProjectManager.getSelectFields(bidWay, true);
        // 查询实际数据
        JSONObject obj = baseMapper.getProjectByPrimaryKey(selectFields, projectId);
        // 转换实体对象
        AbstractProject project = obj.toBean(bidWay.getTargetClass());
        //采购单位(招标单位)
        if (obj.get("bidding_organize_info") != null) {
            project.setBiddingOrganizeInfo(JSONUtil.toBean(obj.get("bidding_organize_info").toString(), OrganizeInfo.class));
        }
        //代理机构agencyOrganizeInfo
        if (obj.get("agency_organize_info") != null) {
            project.setAgencyOrganizeInfo(JSONUtil.toBean(obj.get("agency_organize_info").toString(), OrganizeInfo.class));
        }
        // 附件信息
        if (obj.get("attachment") != null) {
            List<Object> attachment = JSONUtil.toList(obj.get("attachment").toString(), Object.class);
            Attachments instance = Attachments.getInstance(attachment);
            project.setAttachment(instance);
        }
        return project;
    }

    @Override
    public AbstractProject getByPrimaryKey(Long projectId) {
        if (projectId == null) {
            return null;
        }
        QueryWrapper<AbstractProject> wrapper = AbstractProject.wrapper("bid_way", "common_type", "project_name");
        wrapper.eq("id", projectId);
        // 未查询到数据直接返回
        AbstractProject one = getOne(wrapper);
        if (one == null) {
            return null;
        }
        // 项目类型为空的数据直接返回
        if (one.getBidWay() == null) {
            return null;
        }
        return getByPrimaryKey(projectId, Enums.of(BidWayEnum.class, one.getBidWay()));
    }

    @Override
    public boolean updateProjectById(AbstractProject project) {
        Integer bidWay = project.getBidWay();
        if (bidWay == null) {
            return false;
        }
        Long projectId = project.getId();
        if (projectId == null) {
            return false;
        }
        List<String> selectFields = AbstractProjectManager.getSelectFields(Enums.of(BidWayEnum.class, bidWay), true);
        return insertOrUpdateProject(project, selectFields);
    }

    /**
     * 编辑公告 更新项目信息
     *
     * @param project
     */
    @Override
    public boolean updateNoticeProjectRelevant(AbstractProject project) {
        int count = baseMapper.updateNoticeProjcetRelevant(project);
        return count > 0;
    }

    @Override
    public boolean insertOrUpdateProject(AbstractProject project, Collection<String> fields) {
        AbstractProjectManager projectManager = project.to(AbstractProjectManager.class);
        // 如果项目编号为空设置一个新的项目编号
        if (StrUtil.isEmpty(project.getProjectCode())) {
            projectManager.genCode();
            project.setProjectCode(projectManager.getProjectCode());
        }
        // 组装需要新增或者需要更新的值
        Map<String, Object> updateMap = new HashMap<>();
        for (String selectField : fields) {
            // 过滤id属性是避免在更新时修改
            if ("id".equals(selectField)) {
                continue;
            }
            Object value = ReflectUtil.getFieldValue(project, StrUtil.toCamelCase(selectField));
            if (value == null) {
                continue;
            }
            //招标单位|代理机构
            if ("bidding_organize_info".equals(selectField) || "agency_organize_info".equals(selectField)) {
                value = JSONUtil.toJsonStr(JSONUtil.parseObj(value));
            }
            updateMap.put(selectField, value);
        }
        // 判断是更新操作还是新增操作
        boolean insertStatus = project.getId() == null;

        if (insertStatus) {
            //设置招标项目编号
            String tenderProjectCode = generateTenderProjectCode();
            project.setTenderProjectCode(tenderProjectCode);
            updateMap.put("tender_project_code", tenderProjectCode);
            // 设置审核状态
            project.setAuditStatus(AuditStatusEnum.PASSED.getCode());
            // 设置公共属性
            project.buildBaseData(1);
            return baseMapper.insertProject(project.getId(), updateMap) > 0;
        }
        return baseMapper.updateProjectById(project.getId(), updateMap) > 0;
    }

    /**
     * 判断是否是邀请投标
     *
     * @param id
     * @return
     */
    @Override
    public boolean invitationFlag(Long id) {
        Integer commonType = baseMapper.invitationFlag(id);
        return Enums.equals(CommonTypeEnum.INVITE, commonType);
    }

    /**
     * 判断是否需要报名
     *
     * @param id
     * @return
     */
    @Override
    public boolean signUpFlag(Long id) {
        Integer signUpFlag = baseMapper.signUpFlag(id);
        return Enums.equals(LogicEnum.YES, signUpFlag);
    }

    /**
     * 查询是否评审
     *
     * @param id
     * @return
     */
    @Override
    public boolean findReviewFlag(String id) {
        int reviewFlag = baseMapper.findReviewFlag(id);
        return Enums.equals(LogicEnum.YES, reviewFlag);
    }

    @Override
    public CommonTypeEnum getCommonType(Long projectId) {
        if (projectId == null) {
            return null;
        }
        AbstractProject project = getByPrimaryKey(projectId);
        return project.to(AbstractProjectManager.class).getCommonTypeEnum();
    }

    @Override
    @SneakyThrows
    public BidProject getBidProjectById(Long id) {
        if (id == null) {
            //TODO
//            throw new DataException("主键Id为空");
        }
        return baseMapper.getBidProjectById(id);
    }

    @Override
    public AbstractProject getProjectBySectionId(Long sectionId) {
        if (null == sectionId) {
            log.warn("获取项目信息失败，标段Id为空");
            return new AbstractProject();
        }
        return baseMapper.getProjectBySectionId(sectionId);
    }

    @Override
    public List<AbstractProject> listProjectAllFieldsDTO() {
        return baseMapper.listProjectAllFieldsDTO();
    }

    /**
     * @Description: 生成招标项目编号(目前只支持政府采购)
     * @Author: zhongdl
     * @Date:2022/2/21 11:35
     * @return: {@link String }
     **/
    @Override
    public String generateTenderProjectCode() {
        //获得最大的项目编号
        Integer maxNum = baseMapper.getMaxCodeNew();
        if (null == maxNum) {
            maxNum = 0;
        }
        Long NewTenderProjectCode = Long.valueOf(maxNum) + 1;
        StringBuilder buffer = new StringBuilder();
        int length = 7 - NewTenderProjectCode.toString().length();
        for (int i = 0; i < length; i++) {
            buffer.append("0");
        }
        buffer.append(NewTenderProjectCode);
        //项目编号后缀
        String projectCodeSuffix = DataDockConfig.projectCodeSuffix;
        buffer.append(projectCodeSuffix);
        String tenderProjectCode = DataDockConfig.platformCode + buffer;
        return tenderProjectCode;
    }

    /**
     * @Description:
     *
     * @author yuezheng
     * @param
     * @return java.lang.Boolean
     * @date 2022/6/30 16:25
     */
    @Override
    public Boolean deleteProjectById(Long id) {
        AbstractProject project = new AbstractProject();
        project.setId(id);
        project.setDeleteFlag(1);
        int update = this.baseMapper.updateById(project);
        return update > 0 ? true : false;
    }
}
